
import Foundation


enum LogLevel: String {

   
    case info

   
    case debug

   
    case warning

    case error
}


struct LogMessage {

    let date: Date = Date()

    let level: LogLevel

    let file: String

    let function: String

    let line: Int

    let text: String

    init(text: String, level: LogLevel, file: String, function: String, line: Int) {
        self.text = text
        self.level = level
        self.file = file.components(separatedBy: "/").last ?? file
        self.function = function
        self.line = line
    }

    
    func ndt7Description() -> String {
        let logDate = date.toString()
        let queName = queueName() ?? ""
        let logLevel = level.rawValue
        return "\(logDate) [ndt7] [\(queName)] [\(file )-\(function):\(line)]: (\(logLevel)) \(text)"
    }
}


protocol Logger {

   
    func addLogMessage(_ logMessage: LogMessage)
}


class LogManager {

    private static var loggers = [Logger]()
    private static var logLevels = Set<LogLevel>()

   
    class func addLogger(_ logger: Logger) {
        loggers.append(logger)
    }

    class func removeAllLoggers() {
        loggers.removeAll()
    }

  
    class func addLogLevel(_ logLevel: LogLevel) {
        logLevels.insert(logLevel)
    }

  
    class func addAllLogLevels() {
        logLevels.insert(.info)
        logLevels.insert(.debug)
        logLevels.insert(.warning)
        logLevels.insert(.error)
    }

   
    class func removeLogLevel(_ logLevel: LogLevel) {
        logLevels.remove(logLevel)
    }

    class func removeAllLoggLevels() {
        logLevels.removeAll()
    }

  
    class func addLogMessage(_ logMessage: LogMessage) {
        guard logLevels.contains(logMessage.level) else { return }
        loggers.forEach { $0.addLogMessage(logMessage) }
    }
}


func logNDT7(_ text: @autoclosure () -> Any,
             _ logLevel: LogLevel = .info,
             _ file: String = #file,
             _ function: String = #function,
             _ line: Int = #line) {
    LogManager.addLogMessage(LogMessage(text: "\(text())", level: logLevel, file: file, function: function, line: line))
}
